import { Subject } from 'rxjs';
import { ElementRef } from '@angular/core';
import * as G6 from '@antv/g6';
const grid = new G6.Grid();

const defaultNodeStyle = {
    fill: '#3399FF',
    stroke: '#3399FF',
    radius: 4,
};

const defaultEdgeStyle = {
    stroke: '#ccc',
    radius: 10,
    offset: 15,
    endArrow: {
        path: 'M 0,0 L 12, 6 L 9,0 L 12, -6 Z',
        fill: '#ccc',
        d: -20,
    },
};

const defaultStateStyles = {
    hover: {
        stroke: '#C0C4CC',
        lineWidth: 1,
    },
};
const defaultLabelCfg = {
    style: {
        fill: '#ffffff',
        fontSize: 12,
    },
};

export class G6GraphTool {
    static current = new G6GraphTool();
    private graph: G6.Graph;
    private treeGraph: G6.TreeGraph;
    nodeItemClick$ = new Subject();

    constructor() {
        G6.registerNode(
            'icon-node',
            {
                options: {
                    size: [60, 20],
                    stroke: '#94bbd4',
                    fill: '#94bbd4',
                },
                draw(cfg: any, group) {
                    const styles = this.getShapeStyle(cfg);
                    const { labelCfg = {} } = cfg;

                    const w = styles.width;
                    const h = styles.height;

                    const keyShape = group.addShape('rect', {
                        attrs: {
                            ...styles,
                            x: -w / 2,
                            y: -h / 2,
                        },
                    });

                    /**
                     * leftIcon 格式如下：
                     *  {
                     *    style: ShapeStyle;
                     *    img: ''
                     *  }
                     */
                    const { style, img } = {
                        style: {
                            fill: '#FFFFFF10',
                            stroke: '#FFFFFF10',
                        },
                        img: '../../../../../assets/images/setting.png',
                    }
                    group.addShape('rect', {
                        attrs: {
                            x: w / 2 - 33,
                            y: -19,
                            width: 32,
                            height: 38,
                            fill: '#c6e3f5',
                            ...style,
                        },
                        name: 'image-button'
                    });

                    group.addShape('image', {
                        attrs: {
                            x: 34,
                            y: -10,
                            width: 20,
                            height: 20,
                            img,
                        },
                        name: 'image-shape',
                    });

                    if (cfg.label) {
                        let txt: string = cfg.label;
                        if (txt.length > 8) {
                            txt = txt.substr(0, 8) + '...';
                        }
                        group.addShape('text', {
                            attrs: {
                                ...labelCfg.style,
                                fontSize: 10,
                                text: txt,
                                x: 5 - w / 2,
                                y: 27 - h / 2,
                            },
                        });
                    }

                    return keyShape;
                },
                update: undefined
            },
            'rect',
        );

        G6.registerEdge('flow-line', {
            draw(cfg, group) {
                const startPoint = cfg.startPoint;
                const endPoint = cfg.endPoint;

                const { style } = cfg;
                const shape = group.addShape('path', {
                    attrs: {
                        stroke: style.stroke,
                        endArrow: style.endArrow,
                        path: [
                            ['M', startPoint.x, startPoint.y],
                            ['L', startPoint.x, (startPoint.y + endPoint.y) / 2],
                            ['L', endPoint.x, (startPoint.y + endPoint.y) / 2],
                            ['L', endPoint.x, endPoint.y],
                        ],
                    },
                });

                return shape;
            },
        });
    }
    renderNodeGraph(container: ElementRef<HTMLDivElement>, data, rankdir, miniMapContainer: ElementRef<HTMLDivElement>) {
        const defaultLayout = {
            type: 'dagre',
            rankdir, // 可选，默认为图的中心
            nodesep: 20, // 可选
            ranksep: 20, // 可选
            align: 'UL'
        };

        document.getElementById('permitNoPageMsg').innerHTML = '';

        const width = container.nativeElement.scrollWidth;
        const height = container.nativeElement.scrollHeight || 500;


        const minimap = new G6.Minimap(
            {
                container: miniMapContainer.nativeElement,
                type: 'delegate',
            }
        );
        if (!this.graph) {
            this.graph = new G6.Graph({
                container: container.nativeElement,
                width,
                height,
                linkCenter: true,
                plugins: [grid, minimap],
                fitCenter: true,
                // fitViewPadding: [20, 40, 50, 20],
                modes: {
                    default: ['drag-canvas', 'zoom-canvas', 'drag-node'],
                },
                defaultNode: {
                    type: 'icon-node',
                    size: [120, 40],
                    style: defaultNodeStyle,
                    labelCfg: defaultLabelCfg,
                },
                defaultEdge: {
                    type: 'polyline',//'flow-line',
                    style: defaultEdgeStyle,
                },
                nodeStateStyles: defaultStateStyles,
                edgeStateStyles: defaultStateStyles,
                layout: defaultLayout,
            });

            this.graph.on('node:mouseenter', (evt) => {
                const { item } = evt;
                this.graph.setItemState(item, 'hover', true);
            });

            this.graph.on('node:mouseleave', (evt) => {
                const { item } = evt;
                this.graph.setItemState(item, 'hover', false);
            });

            this.graph.on('node:click', (evt) => {
                const { item, target } = evt;
                const name = target.get('name');

                if (name === 'image-button' || name == 'image-shape') {
                    const model = item.getModel();
                    this.nodeItemClick$.next(model);
                }

            });
        }
        this.graph.node(node => {
            node.style = defaultNodeStyle;
            node.style.fill = node.color;
            node.style.stroke = node.color;

            if (node.color == '#C0C4CC') {
                node.labelCfg = defaultLabelCfg;
                node.labelCfg.style.fill = "#606266";
            }

            return node;
        })

        this.graph.clear();
        this.graph.data(data);
        this.graph.render();

        this.graph.updateLayout(defaultLayout);
        this.graph.fitCenter();
    }

    clean() {
        if (this.graph) {
            this.graph.clear();
        }
    }

    destroy() {
        this.graph = null;
    }

    renderNodeTreeGraph(container, data, onSettingClickHandle?) {
        const defaultLayout = {
            type: 'dagre',
            rankdir: 'TB', // 可选，默认为图的中心
            nodesep: 20, // 可选
            ranksep: 50, // 可选
        };

        const width = container.nativeElement.scrollWidth;
        const height = container.nativeElement.scrollHeight || 500;

        if (!this.graph) {
            this.graph = new G6.Graph({
                container: container.nativeElement,
                width,
                height,
                linkCenter: true,
                plugins: [grid],
                fitCenter: true,
                fitViewPadding: [20, 40, 50, 20],
                modes: {
                    default: ['drag-canvas', 'zoom-canvas', 'drag-node'],
                },
                defaultNode: {
                    type: 'icon-node',
                    size: [120, 40],
                    style: defaultNodeStyle,
                    labelCfg: defaultLabelCfg,
                },
                defaultEdge: {
                    type: 'flow-line',
                    style: defaultEdgeStyle,
                },
                nodeStateStyles: defaultStateStyles,
                edgeStateStyles: defaultStateStyles,
                layout: defaultLayout,
            });

            this.graph.on('node:mouseenter', (evt) => {
                const { item } = evt;
                this.graph.setItemState(item, 'hover', true);
            });

            this.graph.on('node:mouseleave', (evt) => {
                const { item } = evt;
                this.graph.setItemState(item, 'hover', false);
            });

            this.graph.on('node:click', (evt) => {
                const { item, target } = evt;
                const targetType = target.get('type');
                const name = target.get('name');

                if (targetType === 'image') {
                    const model = item.getModel();
                    if (name === 'image-shape') {
                        // TODO:
                        onSettingClickHandle && onSettingClickHandle(model);
                    }
                }
            });
        }

        this.graph.clear();
        this.graph.data(data);
        this.graph.render();
        this.graph.fitView();


    }

}